from datetime import datetime, timedelta
from typing import Optional
from sqlalchemy.orm import Session
from passlib.context import CryptContext
from jose import JWTError, jwt
import logging
import uuid

from app.models.database import User
from app.models.schemas import UserCreate, UserLogin, UserInfo, Token
from app.config import settings

logger = logging.getLogger(__name__)

# Password hashing
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")

class SimpleAuthService:
    """简化的认证服务 - 使用同步SQLAlchemy"""
    
    def __init__(self):
        self.secret_key = settings.SECRET_KEY
        self.algorithm = "HS256"
        self.access_token_expire_minutes = settings.ACCESS_TOKEN_EXPIRE_MINUTES
        self.refresh_token_expire_days = settings.REFRESH_TOKEN_EXPIRE_DAYS
    
    def verify_password(self, plain_password: str, hashed_password: str) -> bool:
        """验证密码"""
        return pwd_context.verify(plain_password, hashed_password)
    
    def get_password_hash(self, password: str) -> str:
        """生成密码哈希"""
        return pwd_context.hash(password)
    
    def create_access_token(self, data: dict, expires_delta: Optional[timedelta] = None) -> str:
        """创建访问令牌"""
        to_encode = data.copy()
        if expires_delta:
            expire = datetime.utcnow() + expires_delta
        else:
            expire = datetime.utcnow() + timedelta(minutes=self.access_token_expire_minutes)
        
        to_encode.update({"exp": expire, "type": "access"})
        encoded_jwt = jwt.encode(to_encode, self.secret_key, algorithm=self.algorithm)
        return encoded_jwt
    
    def create_refresh_token(self, data: dict) -> str:
        """创建刷新令牌"""
        to_encode = data.copy()
        expire = datetime.utcnow() + timedelta(days=self.refresh_token_expire_days)
        to_encode.update({"exp": expire, "type": "refresh"})
        encoded_jwt = jwt.encode(to_encode, self.secret_key, algorithm=self.algorithm)
        return encoded_jwt
    
    def verify_token(self, token: str, token_type: str = "access") -> Optional[dict]:
        """验证令牌"""
        try:
            payload = jwt.decode(token, self.secret_key, algorithms=[self.algorithm])
            if payload.get("type") != token_type:
                return None
            return payload
        except JWTError:
            return None
    
    def create_user(self, user_data: UserCreate, db: Session) -> UserInfo:
        """创建用户"""
        try:
            # 检查用户名是否已存在
            existing_user = db.query(User).filter(
                (User.username == user_data.username) | (User.email == user_data.email)
            ).first()
            
            if existing_user:
                raise ValueError("用户名或邮箱已存在")
            
            # 创建新用户
            user = User(
                id=str(uuid.uuid4()),
                username=user_data.username,
                email=user_data.email,
                full_name=user_data.full_name,
                hashed_password=self.get_password_hash(user_data.password),
                role="user",
                is_active=True
            )
            
            db.add(user)
            db.commit()
            db.refresh(user)
            
            logger.info(f"User created: {user.username}")
            return self._user_to_info(user)
            
        except Exception as e:
            db.rollback()
            logger.error(f"Failed to create user: {e}")
            raise
    
    def authenticate_user(self, username: str, password: str, db: Session) -> Optional[User]:
        """验证用户凭据"""
        try:
            user = db.query(User).filter(User.username == username).first()
            if not user:
                return None
            
            if not self.verify_password(password, user.hashed_password):
                return None
            
            if not user.is_active:
                return None
            
            return user
            
        except Exception as e:
            logger.error(f"Authentication error: {e}")
            return None
    
    def login(self, login_data: UserLogin, db: Session) -> Optional[Token]:
        """用户登录"""
        try:
            user = self.authenticate_user(login_data.username, login_data.password, db)
            if not user:
                return None
            
            # 更新最后登录时间
            user.last_login = datetime.utcnow()
            db.commit()
            
            # 创建令牌
            access_token = self.create_access_token(
                data={"sub": user.id, "username": user.username}
            )
            refresh_token = self.create_refresh_token(
                data={"sub": user.id, "username": user.username}
            )
            
            logger.info(f"User logged in: {user.username}")
            return Token(
                access_token=access_token,
                refresh_token=refresh_token,
                token_type="bearer"
            )
            
        except Exception as e:
            logger.error(f"Login error: {e}")
            return None
    
    def refresh_token(self, refresh_token: str, db: Session) -> Optional[Token]:
        """刷新访问令牌"""
        try:
            payload = self.verify_token(refresh_token, "refresh")
            if not payload:
                return None
            
            user_id = payload.get("sub")
            username = payload.get("username")
            
            if not user_id or not username:
                return None
            
            # 验证用户仍然存在且活跃
            user = db.query(User).filter(User.id == user_id).first()
            if not user or not user.is_active:
                return None
            
            # 创建新的令牌
            access_token = self.create_access_token(
                data={"sub": user.id, "username": user.username}
            )
            new_refresh_token = self.create_refresh_token(
                data={"sub": user.id, "username": user.username}
            )
            
            return Token(
                access_token=access_token,
                refresh_token=new_refresh_token,
                token_type="bearer"
            )
            
        except Exception as e:
            logger.error(f"Token refresh error: {e}")
            return None
    
    def get_user_by_id(self, user_id: str, db: Session) -> Optional[User]:
        """根据ID获取用户"""
        try:
            return db.query(User).filter(User.id == user_id).first()
        except Exception as e:
            logger.error(f"Failed to get user {user_id}: {e}")
            return None
    
    def get_user_by_username(self, username: str, db: Session) -> Optional[User]:
        """根据用户名获取用户"""
        try:
            return db.query(User).filter(User.username == username).first()
        except Exception as e:
            logger.error(f"Failed to get user {username}: {e}")
            return None
    
    def _user_to_info(self, user: User) -> UserInfo:
        """将User对象转换为UserInfo"""
        return UserInfo(
            id=user.id,
            username=user.username,
            email=user.email,
            full_name=user.full_name,
            role=user.role,
            is_active=user.is_active,
            created_at=user.created_at,
            last_login=user.last_login
        )
